use std::{time::Duration, convert::TryInto, io::{Write, stdout}};
use rand::prelude::*;
use termion::raw::IntoRawMode;//随机引擎

use super::enums::*;//基本枚举值
use super::blocks::*;//像素块结构体

//定义整个地图结构体
#[derive(Debug)]
pub struct Maps {
    pub pixels: Vec<Vec<Pixel>>,        //像素块 二维可变数组
    pub size: (usize, usize),           //尺寸
    pub head_loc: (usize, usize),       //蛇头位置
    pub tail_loc: (usize, usize),       //蛇尾位置
    pub level: usize,
    pub score: usize,
    speed:u64,
    welcome: &'static str
}

impl Maps {
    //创建新地图
    pub fn new(x: usize, y: usize) -> Self {
        let mut pixels: Vec<Vec<Pixel>> = Vec::new();//生成空白地图
        for _x in 0..x {
            let mut pixelss: Vec<Pixel> = Vec::new();
            for _y in 0..y {
                pixelss.push(Pixel::new(_x, _y, x, y));
            }
            pixels.push(pixelss.clone());
        }
        for _y in 0..y {
            pixels[0][_y].set_framey();              //初始化上边框
            pixels[x-1][_y].set_framey();            //初始化下边框
        }
        for _x in 0..x {
            pixels[_x][0].set_framel();              //初始化左边框
            pixels[_x][y-1].set_framer();            //初始化右边框
        }

        Self {
            pixels,
            size: (x, y),
            head_loc: (0,0),
            tail_loc: (0,0),
            level: 1,
            score: 0,
            speed: 300,
            welcome: "欢迎进入贪吃蛇游戏，游戏马上开始！"
        }
    }
    //创建初始的蛇
    pub fn set_snake(&mut self, long: usize) -> &mut Self {
        let mut rng: ThreadRng = thread_rng();                                  //随机数引擎
        let x: usize = rng.gen_range(long+1, self.size.0-long-1);      
        let y: usize = rng.gen_range(long+1, self.size.1-long-1);
        self.tail_loc = (x, y);                                                 //随机确定蛇尾位置
        self.head_loc = (x, y);
        let way: Direction = to_direction(rng.gen_range(1, 5));        //生成随机方向
        self.pixels[self.tail_loc.0][self.tail_loc.1].set_tail(way);                                        //初始化蛇尾
        self.head_loc = self.pixels[self.head_loc.0][self.head_loc.1].follow;//找到下一个位置
        for _ in 2..long {
            self.pixels[self.head_loc.0][self.head_loc.1].set_body(way);        //初始化为蛇身
            self.head_loc = self.pixels[self.head_loc.0][self.head_loc.1].follow;//找到下一个位置
        }
        self.pixels[self.head_loc.0][self.head_loc.1].set_head(way);            //初始化为蛇头
        self
    }
    //放置果子
    pub fn set_food (&mut self, mut num: usize) -> &mut Self{
        loop {
            if num == 0 {break;}
            let mut rng: ThreadRng = thread_rng();                              //随机数引擎
            let x: usize = rng.gen_range(1, self.size.0-1);            //生成随机横轴
            let y: usize = rng.gen_range(1, self.size.1-1);            //生成随机纵轴
            if self.pixels[x][y].is_what == IsWhat::Block {
                    self.pixels[x][y].set_food();                               //设为果
                    num -= 1;
            }
            continue;
        }
        self
    }
    //执行转向操作
    pub fn judge_to_turn (&mut self, new: i32) -> &mut Self {
        let now = self.pixels[self.head_loc.0][self.head_loc.1].next_way.get_direction();
        if abs(abs(now - new + 1) - 2) != 1 && new != 0 {                                                //判断可转向
            self.pixels[self.head_loc.0][self.head_loc.1].set_way(to_direction(new));        //转向
        }
        self
    }
    //判断蛇头前移后状态
    pub fn judge_if_move (&self) -> Todo {
        let loc = self.pixels[self.head_loc.0][self.head_loc.1].follow;  //下一个位置
        match self.pixels[loc.0][loc.1].is_what {//是什么
            IsWhat::Framel | IsWhat::Framer | IsWhat::Framey | IsWhat::Head | 
            IsWhat::Body | IsWhat::Tail => Todo::Die,
            IsWhat::Block => Todo::Move,
            IsWhat::Food => Todo::Grow,
        }
    }
    //执行移动操作
    pub fn do_move (&mut self) -> bool{
        match self.judge_if_move() {
            Todo::Die => {                                      //失败
                println!("啊哈!大侠请重新来过!");                  //输出结束语
                true
            }Todo::Move => {                                    //移动
                self.move_head().move_tail();                   //移动头.尾
                false
            }Todo::Grow => {                                    //生长
                self.move_head().set_food(1).score += 1;    //移动头.生成新果.加分
                self.level = self.score / 10 + 1;               //升级
                self.speed = 300/self.level as u64;             //速度跟随等级
                false
            }            
        }
    }
    //移动蛇头，并更新蛇头位置
    pub fn move_head (&mut self) -> &mut Self {
        let way: Direction = self.pixels[self.head_loc.0][self.head_loc.1].next_way;//获取蛇头移动方向
        self.pixels[self.head_loc.0][self.head_loc.1].head_to_body();                //将原位置设为蛇身
        self.head_loc = self.pixels[self.head_loc.0][self.head_loc.1].follow;  //找到下一个位置
        self.pixels[self.head_loc.0][self.head_loc.1].set_head(way);                 //将该位置设为蛇头
        self
    }
    //移动蛇尾，并更新蛇尾位置
    pub fn move_tail (&mut self) -> &mut Self {
        let loc: (usize, usize) = self.tail_loc;                                     //获取蛇尾位置
        self.tail_loc = self.pixels[loc.0][loc.1].follow;                      //找到下一个位置
        self.pixels[loc.0][loc.1].set_block();                                       //将原位置设为空白
        self.pixels[self.tail_loc.0][self.tail_loc.1].body_to_tail();                //将该位置设为蛇尾
        self
    }
    //显示欢迎界面
    pub fn show_welcome (&self) -> &Self {
        goto_clear((self.size.0/2).try_into().unwrap(), 1, String::from(self.welcome));
        self
    }
    //显示地图
    pub fn show (&self) -> &Self{
        goto_clear(1, 1, String::from(""));
        for x in 0..self.size.0 {
            for y in 0..self.size.1 {
                &self.pixels[x][y].print();
            }
            println!();
        }
        println!(
            "W:↑, S:↓, A:←, D:→, Q:quit, Level: {}   Score: {}"
            ,self.level 
            ,self.score
        );
        self
    }
    //休眠
    pub fn sleep (&self) -> &Self {
        std::thread::sleep(Duration::from_millis(self.speed));
        self
    }


}


//清屏,定位,输出文本
fn goto_clear (x: u16, y: u16, strs: String) {
    let stdout = stdout();
    let mut stdout = stdout.into_raw_mode().unwrap();
    write!(stdout, "{}{}{}{}",
        termion::clear::All,                             //清屏
        termion::cursor::Goto(x, y),                     //定位
        strs,                                            //打印内容(如果有)
        termion::cursor::Hide)           //隐藏光标
        .unwrap();
    stdout.flush().unwrap();                            //清空缓存
}
